package org.cxfexample.invoker;

import java.util.List;

import javax.xml.namespace.QName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.common.util.ClassHelper;
import org.apache.cxf.headers.Header;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.service.invoker.AbstractInvoker;
import org.apache.cxf.service.model.OperationInfo;
import org.cxfexample.helloworld.HelloWorldImpl;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

public class AuthenticationInvoker extends AbstractInvoker {

	private Log logger = LogFactory.getLog(this.getClass());
	
	
	private String userName;
	private String password;
	private Object bean;
	
	@Override
	public Object getServiceObject(Exchange context) {
		this.logger.info("invoke getServiceObject");
		this.logger.info("parameter type:"+context.getClass().toString());
		return bean;
	}

	public AuthenticationInvoker(Object bean) {
		this.bean = bean;
	}
	
	@Override
	   public Object invoke(Exchange exchange, Object o) { 
		
	      // Get method and class details from the request 
	      OperationInfo opInfo = exchange.get(OperationInfo.class);
	      String methodName = opInfo.getInputName();
	      Class<?> realClass = ClassHelper.getRealClass(bean);
	      QName qnameOrderCredential = new QName("OrderCredentials");         
	       // Perform security check only if the service class is OrderProcessImpl
	      // and method name is processOrder
	      
	      if (realClass == HelloWorldImpl.class && "processOrder". equals(methodName)) {
	         List<?> list = (List<?>) exchange.getInMessage().get(Header.HEADER_LIST);
	         for (int  i = 0 ; i< list.size() ; i++  ) {
	            // Get the SOAP header
	            SoapHeader header = (SoapHeader) list.get(i);
	            if(header.getName().equals(qnameOrderCredential)) {                          
	               Element orderCredential= (Element) header.getObject();
	               Node usernamel = orderCredential.getFirstChild();
	               Node passwordel = orderCredential.getLastChild();
	               if (usernamel != null) {
	                  userName = usernamel.getTextContent();
	               }
	               if (passwordel != null) {
	                  password = passwordel.getTextContent();
	               }
	            } else {
	                throw new RuntimeException("Request doesn't contain OrderCredentials namespace");
	            }
	         }            
	         this.logger.info("userName reterived from SOAP Header is " + userName);
	         this.logger.info("password reterived from SOAP Header is " + password);
	         
	         // Perform dummy validation for John
	         if ("John".equalsIgnoreCase(userName) && "password". equalsIgnoreCase(password)) {
	        	 this.logger.info("Authentication successful for John");
	         } else {
	            throw new RuntimeException("Invalid user or password");
	         }
	      } 
	      return super.invoke(exchange,o);
	    }

}
